-module(slug). %% slog sounds lame. decided on slug. could be worse.
-behaviour(gen_server).

-export([ %% all slug:X(...) calls are to make it friendly to hot code changes
    start/0, start/2, stop/1, log_name/1,
    info/1, add_log/2, write/2, write/3
]).

-export([
    init/1, terminate/2, code_change/3,
    handle_call/3, handle_cast/2, handle_info/2
]).

-define(DFORMAT, "~p~n").

-record(log, {name, file, processed, lastupdated, handle}).

start() -> ok.

start(Name, File) ->
    {ok, L} = file:open(File, write),
    NewLog = #log{name = Name, file = File, processed = 0, lastupdated = now(), handle = L},
    gen_server:start_link({local, log_name(Name)}, ?MODULE, [NewLog], []).

stop(Name) -> gen_server:call(log_name(Name), stop).

init([LogState]) -> {ok, LogState}.

add_log(Name, File) -> start(Name, File).

info(Name) -> gen_server:call(log_name(Name), info).

write(Name, Data) -> write(Name, ?DFORMAT, [Data]).

write(Name, Format, Data) -> catch(gen_server:call(log_name(Name), {write, Format, Data})).

write_log(State, Format, Data) ->
    OldC = State#log.processed,
    io:format(State#log.handle, Format, Data),
    State#log{processed = OldC + 1, lastupdated = now()}.

log_name(Name) -> list_to_atom(lists:concat(["slug_log_", Name])). %% unique enough? -- nkg

handle_call(info, _From, LogState) -> {reply, LogState, LogState};

handle_call({write, Format, Data}, _From, State) ->
    NewState = write_log(State, Format, Data),
    {reply, ok, NewState};

handle_call(stop, _From, State) -> {stop, normalStop, State};

handle_call(_, _From, State) -> {noreply, ok, State}.

handle_cast(_Msg, State) -> {noreply, State}.

handle_info(_Info, State) -> {noreply, State}.

terminate(_Reason, _State) -> ok.

code_change(_OldVsn, State, _Extra) -> {ok, State}.

